package com.wtwd.campus.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.common.RespCode;
import com.wtwd.campus.common.RespEntity;
import com.wtwd.campus.entity.*;
import com.wtwd.campus.service.*;
import com.wtwd.campus.utils.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @Author ldaoliang
 * @Date create in 13:04 2021/6/21
 * @Description
 */
@RestController
@RequestMapping("/customer")
public class CustomerController {

    private static final Logger logger = LoggerFactory.getLogger(CustomerController.class);

    @Autowired
    private CustomerService customerService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    private CommandSendUtils commandSendUtils;
    @Autowired
    private WhiteListService whiteListService;
    @Autowired
    private DeviceClassPatternService deviceClassPatternService;

    private static ExecutorService threadPool = new ThreadPoolExecutor(1,
            5,
            1L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(4),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    /**
     * 获取AccessToken
     *
     * @param appKey    key
     * @param appSecret secret加密结果
     * @return
     */
    @GetMapping("/getAccessToken")
    public RespEntity getAccessToken(@RequestParam("appKey") String appKey, @RequestParam("appSecret") String appSecret) {
        logger.info("getAccessToken : appKey [{}],appSecret[{}]", appKey, appSecret);
        if (StringUtils.isBlank(appKey) || StringUtils.isBlank(appSecret)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        // 1、校验appKey和密码正确性
        SysCustomer sysCustomer = customerService.getSysCustomerByAppKey(appKey);
        if (sysCustomer == null) {
            return new RespEntity(RespCode.APP_KEY_NOT_FOUND);
        }
        String md5Secret = MD5Utils.encode(sysCustomer.getAppSecret());
        if (!appSecret.equalsIgnoreCase(md5Secret)) {
            return new RespEntity(RespCode.APP_SECRET_ERROR);
        }
        if (sysCustomer.getDisableSwitch().intValue() == Constants.DISABLED) {
            return new RespEntity(RespCode.APP_KEY_DISABLE);
        }
        // 创建token
        String[] token = redisService.createCustomerToken(sysCustomer.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("accessToken", token[0]);
        jsonObject.put("refreshToken", token[1]);
        return new RespEntity(RespCode.SUCCESS, jsonObject);
    }

    /**
     * 刷新accessToken
     *
     * @param appKey
     * @param refreshToken
     * @return
     */
    @GetMapping("/refreshAccessToken")
    public RespEntity refreshAccessToken(@RequestParam("appKey") String appKey, @RequestParam("refreshToken") String refreshToken) {
        logger.info("refreshAccessToken : appKey = [{}], refreshToken = [{}]", appKey, refreshToken);
        if (StringUtils.isBlank(appKey) || StringUtils.isBlank(refreshToken)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        // 根据appKey查找客户id
        SysCustomer sysCustomer = customerService.getSysCustomerByAppKey(appKey);
        if (sysCustomer == null) {
            return new RespEntity(RespCode.APP_KEY_NOT_FOUND);
        }
        if (sysCustomer.getDisableSwitch().intValue() == Constants.DISABLED) {
            return new RespEntity(RespCode.APP_KEY_DISABLE);
        }
        // redis里面校验refreshToken的正确性
        boolean validRefreshTokenResult = redisService.verifyRefreshToken(sysCustomer.getId(), refreshToken);
        if (!validRefreshTokenResult) {
            return new RespEntity(RespCode.REFRESH_TOKEN_ERROR);
        }
        // 创建token
        String[] token = redisService.createCustomerToken(sysCustomer.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("accessToken", token[0]);
        jsonObject.put("refreshToken", token[1]);
        return new RespEntity(RespCode.SUCCESS, jsonObject);
    }

    /**
     * TODO 待确认
     * 更新推送地址
     *
     * @param jsonObject pushUrl:推送地址
     * @return
     */
    @PutMapping("/updatePushUrl")
    public RespEntity updatePushUrl(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        String pushUrl = jsonObject.getString("pushUrl");
        logger.info("updatePushUrl : [{}]", pushUrl);
        String accessToken = request.getHeader("Access-Token");
        Integer customerId = redisService.customerToken2CustomerId(accessToken);
        if (customerId == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        // 先修改数据库状态，再提交线程池任务
        customerService.updateCustomerPushUrl(customerId, pushUrl, Constants.PUSH_VERIFYING);
        threadPool.submit(() -> {
            System.out.println("线程: " + Thread.currentThread().getName() + " 开始执行");
            JSONObject pushTestJson = new JSONObject();
            pushTestJson.put("messageType", 0);
            pushTestJson.put("dataType", 0);
            boolean getResponse = false;
            try {
                String result = HttpclientUtil.httpPost(pushUrl, pushTestJson);
                JSONObject json = JSONObject.parseObject(result);
                if (String.valueOf(json.get("code")).equals("1")) {
                    getResponse = true;
                }
            } catch (Exception e) {
                logger.error("推送地址响应失败");
            }
            System.out.println("设置结果" + getResponse);
            if (getResponse) {
                // 更新数据库
                customerService.updateCustomerPushUrl(customerId, pushUrl, Constants.PUSH_EFFECT);
            } else {
                customerService.updateCustomerPushUrl(customerId, pushUrl, Constants.PUSH_INVALID);
            }
        });
        return new RespEntity(RespCode.VERIFY_PUSH_DATA);
    }

    /**
     * TODO 待确认
     * 获取推送地址信息
     *
     * @param request
     * @return
     */
    @GetMapping("/getPushUrlMsg")
    public RespEntity getPushUrlMsg(HttpServletRequest request) {
        logger.info("获取推送地址信息");
        String accessToken = request.getHeader("Access-Token");
        Integer customerId = redisService.customerToken2CustomerId(accessToken);
        if (customerId == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        SysCustomer sysCustomer = customerService.getSysCustomerById(customerId);
        // 推送地址为空，则返回未设置
        if (StringUtils.isBlank(sysCustomer.getPushUrl())) {
            return new RespEntity(RespCode.NOT_SET_PUSH_URL);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("pushUrl", sysCustomer.getPushUrl());
        jsonObject.put("status", sysCustomer.getPushStatus());
        return new RespEntity(RespCode.SUCCESS, jsonObject);
    }

    /**
     * 获取设备列表
     *
     * @param imei     输入Imei左模糊查询
     * @param request
     * @param currPage
     * @param pageSize
     * @return
     */
    @GetMapping("/getDeviceList")
    public RespEntity deviceList(@RequestParam("imei") String imei, @RequestParam("currPage") Integer currPage,
                                 @RequestParam("pageSize") Integer pageSize, HttpServletRequest request) {
        logger.info("getDeviceList : imei = {}, currPage = {} , pageSize = {}", imei, currPage, pageSize);
        String accessToken = request.getHeader("Access-Token");
        Integer customerId = redisService.customerToken2CustomerId(accessToken);
        if (customerId == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Map<String, Object> map = deviceInfoService.getCustomerDeviceList(customerId, imei, currPage, pageSize);
        return new RespEntity(RespCode.SUCCESS, map);
    }

    /**
     * 获取设备最新的一条定位数据
     *
     * @param imei 具体的imei
     * @return
     */
    @GetMapping("/getDeviceLatelyLocation")
    public RespEntity getDeviceLatelyLocation(@RequestParam("imei") String imei, HttpServletRequest request) {
        logger.info("getDeviceLatelyLocation : imei = [{}]", imei);
        if (StringUtils.isBlank(imei)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        LocationDataVo locationDataVo = deviceInfoService.getDeviceLastLocation(imei);
        return new RespEntity(RespCode.SUCCESS, locationDataVo);
    }

    /**
     * 获取设备的定位轨迹
     *
     * @param imei      imei
     * @param beginTime 开始时间戳
     * @param endTime   结束时间戳
     * @return
     */
    @GetMapping("/getDeviceOrbit")
    public RespEntity getDeviceOrbit(@RequestParam("imei") String imei, @RequestParam("beginTime") Long beginTime,
                                     @RequestParam("endTime") Long endTime, HttpServletRequest request) {
        logger.info("getDeviceOrbit : imei = [{}], beginTime = [{}], endTime = [{}]", imei, beginTime, endTime);
        // 1.判断时间是否为空 跨度是否超过三天
        if (StringUtils.isBlank(imei) || beginTime == null || endTime == null) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        if (endTime - beginTime > 3 * 24 * 60 * 60 * 1000L) {
            return new RespEntity(RespCode.TIME_SPAN_TOO_LARGE);
        }
        // 2.校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        // 3. 返回结果
        List<LocationDataVo> locationDataVoList = deviceInfoService.getDeviceOrbit(imei, beginTime, endTime);
        return new RespEntity(RespCode.SUCCESS, locationDataVoList);
    }

    /**
     * 设置工作模式
     * 针对指令的发送。在线，则返回状态为发送成功，待设备回复结果；不在线不发送
     *
     * @param jsonObject imei,mode,interval
     * @return
     */
    @PostMapping("/setWorkMode")
    public RespEntity setWorkMode(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setWorkMode : param = {}", jsonObject);
        System.out.println("开始时间：" + System.currentTimeMillis());
        // 1.校验参数
        String imei = jsonObject.getString("imei");
        Integer mode = jsonObject.getInteger("mode");
        Integer interval = jsonObject.getInteger("interval");
        if (StringUtils.isBlank(imei) || mode == null || interval == null) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        // 2.校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        // 3.构建指令
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if (!isOnline) {
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        boolean sendResult = commandSendUtils.setDeviceMode(imei, commandNumber, mode, interval, true, 0, false);
        // 4.修改数据库的状态（在线且发送为true的情况需要修改状态）
        if (sendResult) {
            deviceInfoService.updateDeviceModeStatus(imei, commandNumber);
            return new RespEntity(RespCode.SEND_SUCCESS, commandNumber);
        } else {
            return new RespEntity(RespCode.FAILED);
        }
    }

    /**
     * 查询设备定位
     * 设备不在线，直接拒绝
     *
     * @param imei
     * @param request
     * @return
     */
    @GetMapping("/queryLocation")
    public RespEntity queryLocation(@RequestParam("imei") String imei, HttpServletRequest request) {
        logger.info("queryLocation: imei = {}", imei);
        // 校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        // 判断是否在线，不在线不发送
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if (!isOnline) {
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        boolean sendResult = commandSendUtils.queryDeviceLocation(imei, commandNumber, 0, true, false);
        if (sendResult) {
            return new RespEntity(RespCode.SEND_SUCCESS);
        }
        return new RespEntity(RespCode.FAILED);
    }

    /**
     * 查询白名单列表
     *
     * @param imei
     * @return
     */
    @GetMapping("/getWhiteCallList")
    public RespEntity getWhiteCallList(@RequestParam("imei") String imei, HttpServletRequest request) {
        logger.info("getWhiteCallList: imei = {}", imei);
        // 校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        // 查询数据
        List<WhiteCallVo> whiteCallVoList = customerService.getDeviceWhiteCallList(imei);
        return new RespEntity(RespCode.SUCCESS, whiteCallVoList);
    }

    /**
     * 设置白名单
     *
     * @param jsonObject imei,sequence,name,phone,operation
     * @return
     */
    @PostMapping("/setWhiteCall")
    public RespEntity setWhiteCall(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setWhiteCall : param = {}", jsonObject);
        String imei = jsonObject.getString("imei");
        Integer sequence = jsonObject.getInteger("sequence");
        String name = jsonObject.getString("name");
        String phone = jsonObject.getString("phone");
        Integer operation = jsonObject.getInteger("operation");
        // 参数判断
        if (StringUtils.isBlank(imei) || StringUtils.isBlank(name) || StringUtils.isBlank(phone)
                || sequence == null || operation == null) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        // 设备端 1-3 SOS号码  4-6亲情号  7-25
        if (sequence < 7) {
            return new RespEntity(RespCode.WHITE_CALL_SEQ_NEED_LARGE_7);
        }
        // 校验imei
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        DeviceInfo deviceInfo = (DeviceInfo)object;
        // 校验sequence和操作
        RespCode respCode = customerService.verifyWhiteCallSequenceOperation(deviceInfo.getDeviceId(), sequence, operation);
        if (respCode.getCode() != RespCode.SUCCESS.getCode()) {
            return new RespEntity(respCode);
        }
        // 指令处理
        // 3.构建指令
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if (!isOnline) {
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        DeviceWhiteCall deviceWhiteCall = new DeviceWhiteCall();
        deviceWhiteCall.setDeviceId(deviceInfo.getDeviceId());
        deviceWhiteCall.setImei(imei);
        deviceWhiteCall.setName(name);
        deviceWhiteCall.setPhone(phone);
        deviceWhiteCall.setSequence(sequence);
        deviceWhiteCall.setCommandNumber(commandNumber);
        // 增加
        if (operation.intValue() == Constants.OPERATOR_ADD) {
            boolean send = commandSendUtils.addWhiteCall(deviceWhiteCall, isOnline, 0, false);
            if (send) {
                deviceWhiteCall.setStatus(Constants.CLASSES_PATTERN_STAY_ADD);
                whiteListService.addDeviceWhiteCall(deviceWhiteCall);
                return new RespEntity(RespCode.SUCCESS);
            }
        }
        // 删除
        else if (operation.intValue() == Constants.OPERATOR_DEL) {
            boolean send = commandSendUtils.delWhiteCall(imei, commandNumber, sequence, isOnline, 0, false);
            if (send) {
                whiteListService.updateWhiteCallStatus(deviceInfo.getDeviceId(), sequence, Constants.CLASSES_PATTERN_STAY_DELETE, commandNumber);
                return new RespEntity(RespCode.SUCCESS);
            }
        }
        // 更新
        else {
            boolean send = commandSendUtils.updateDeviceWhiteCall(deviceWhiteCall, isOnline, 0, false);
            if (send) {
                whiteListService.updateWhiteCallStatus(deviceInfo.getDeviceId(), sequence, Constants.CLASSES_PATTERN_STAY_UPDATE, commandNumber);
                return new RespEntity(RespCode.SUCCESS);
            }
        }
        return new RespEntity(RespCode.FAILED);
    }

    /**
     * 获取设备课堂模式列表
     *
     * @param imei
     * @param request
     * @return
     */
    @GetMapping("/getClassModeList")
    public RespEntity getClassModeList(@RequestParam("imei") String imei, HttpServletRequest request) {
        logger.info("getWhiteCallList: imei = {}", imei);
        // 校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        // 查询数据
        List<ClassPatternVo> classPatternList = customerService.getDeviceClassPatternList(imei);
        return new RespEntity(RespCode.SUCCESS, classPatternList);
    }

    /**
     * 设置课堂模式
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/setClassMode")
    public RespEntity setClassMode(@RequestBody JSONObject jsonObject) {
        logger.info("setWhiteCall : param = {}", jsonObject);
        String imei = jsonObject.getString("imei");
        Integer sequence = jsonObject.getInteger("sequence");
        String startTime = jsonObject.getString("startTime");
        String endTime = jsonObject.getString("endTime");
        String repeatTime = jsonObject.getString("repeatTime");
        Integer operation = jsonObject.getInteger("operation");
        // 参数判断
        if (StringUtils.isBlank(imei) || StringUtils.isBlank(startTime) || StringUtils.isBlank(endTime)
                || sequence == null || operation == null || StringUtils.isBlank(repeatTime)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        DeviceInfo deviceInfo = deviceInfoService.getDeviceInfoByImei(imei);
        // 校验sequence和操作
        RespCode respCode = customerService.verifyClassPatternSequenceOperation(deviceInfo.getDeviceId(), sequence, operation);
        if (respCode.getCode() != RespCode.SUCCESS.getCode()) {
            return new RespEntity(respCode);
        }
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if (!isOnline) {
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        DeviceClassMode deviceClassMode = new DeviceClassMode();
        deviceClassMode.setCommandNumber(commandNumber);
        deviceClassMode.setImei(imei);
        deviceClassMode.setSequence(sequence);
        deviceClassMode.setDeviceId(deviceInfo.getDeviceId());
        deviceClassMode.setStartTime(startTime);
        deviceClassMode.setEndTime(endTime);
        deviceClassMode.setRepeatTime(repeatTime);
        deviceClassMode.setOnOff(1);
        deviceClassMode.setStatus(Constants.CLASSES_PATTERN_STAY_ADD);
        // 增加
        if (operation.intValue() == Constants.OPERATOR_ADD) {
            boolean send = commandSendUtils.addClassMode(deviceClassMode, isOnline, 0, false);
            if (send) {
                deviceClassPatternService.addDeviceClassPattern(deviceClassMode);
                return new RespEntity(RespCode.SUCCESS);
            }
        }
        // 删除
        else if (operation.intValue() == Constants.OPERATOR_DEL) {
            boolean send = commandSendUtils.delClassMode(imei, commandNumber, sequence, isOnline, 0, false);
            if (send) {
                deviceClassPatternService.updateClassPatternStatus(deviceInfo.getDeviceId(), sequence, Constants.CLASSES_PATTERN_STAY_DELETE, commandNumber);
                return new RespEntity(RespCode.SUCCESS);
            }
        }
        // 更新
        else {
            boolean send = commandSendUtils.updateClassMode(deviceClassMode, isOnline, 0, false);
            if (send) {
                deviceClassPatternService.updateClassPatternStatus(deviceInfo.getDeviceId(), sequence, Constants.CLASSES_PATTERN_STAY_UPDATE, commandNumber);
                return new RespEntity(RespCode.SUCCESS);
            }
        }
        return new RespEntity(RespCode.FAILED);
    }

    /**
     * 监听
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/setMonitor")
    public RespEntity setMonitor(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setMonitor: param = {}", jsonObject);
        String imei = jsonObject.getString("imei");
        String phone = jsonObject.getString("phone");
        if (StringUtils.isBlank(imei) || StringUtils.isBlank(phone)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        // 校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        // 判断是否在线，不在线不发送
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if (!isOnline) {
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        boolean sendResult = commandSendUtils.setMonitorPhone(imei, commandNumber, phone, 0);
        if (sendResult) {
            return new RespEntity(RespCode.SEND_SUCCESS, commandNumber);
        }
        return new RespEntity(RespCode.FAILED);
    }

    /**
     * 闲时自动切换模式
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/autoChangeModeInSleepTime")
    public RespEntity autoChangeMode(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("set autoChangeModeInSleepTime : param = {}", jsonObject);
        String beginTime = jsonObject.getString("beginTime");
        String endTime = jsonObject.getString("endTime");
        Integer flag = jsonObject.getInteger("flag");  // 0-关闭 1-开启
        String imei = jsonObject.getString("imei");
        if (StringUtils.isBlank(beginTime) || StringUtils.isBlank(endTime) || StringUtils.isBlank(imei)
                || flag == null) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if(!isOnline){
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        boolean send = commandSendUtils.setSleepTimeAutoChangeMode(imei, commandNumber, beginTime, endTime, flag, isOnline, 0, false);
        if (send) {
            return new RespEntity(RespCode.SUCCESS);
        } else {
            return new RespEntity(RespCode.FAILED);
        }
    }

    /**
     * 设置开关状态
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/setSwitchOnOff")
    public RespEntity setSwitchOnOff(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setSwitchOnOff : param = {}", jsonObject);
        // type  sos 0-开 1-关   课堂模式 0-关 1-开  白名单 1-开 0-关
        Integer type = jsonObject.getInteger("type");
        Integer onOff = jsonObject.getInteger("onOff");
        String imei = jsonObject.getString("imei");
        if (StringUtils.isBlank(imei) || type == null || onOff == null) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        // 校验设备
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if(!isOnline){
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        boolean send = false;
        if (type == Constants.SWITCH_TYPE_SOS) {
            send = commandSendUtils.setSOSSwitch(imei, commandNumber, onOff == 0 ? 1 : 0, isOnline, 0, false);
        } else if (type == Constants.SWITCH_TYPE_CLASS_PATTERN) {
            send = commandSendUtils.updateClassModeAllSwitch(imei, commandNumber, onOff, isOnline, 0, false);
        } else if (type == Constants.SWITCH_TYPE_WHITE_CALL) {
            send = commandSendUtils.setWhiteCallSwitch(imei, commandNumber, onOff, 0, isOnline, false);
        }
        if (send) {
            return new RespEntity(RespCode.SUCCESS);
        }
        return new RespEntity(RespCode.FAILED);
    }

    /**
     * 设置设备的电子围栏
     *
     * @param jsonObject operation 1-增加 2-删除 3-修改;
     *                   fenceId 围栏Id(修改删除用到)
     *                   fenceName 围栏名
     *                   radius 半径
     *                   fenceType 围栏类型 0-进 1-出
     *                   longitude 经度(GPS84坐标)
     *                   latitude 纬度(GPS84坐标)
     *                   timePeriod 报警时间段  [{beginTime endTime}]
     * @param request
     * @return
     */
    @PostMapping("/setDeviceFence")
    public RespEntity setDeviceFence(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setDeviceFence: param = {}", jsonObject);
        // 先取出所有的数据，再判断数据是否缺失
        Integer operation = jsonObject.getInteger("operation");
        if (operation == null) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        String accessToken = request.getHeader("Access-Token");
        Integer customerId = redisService.customerToken2CustomerId(accessToken);
        // 删除围栏
        if (operation.intValue() == 2) {
            return new RespEntity(customerService.delFence(jsonObject, customerId));
        }
        // 新增或更新围栏
        else {
            return new RespEntity(customerService.addOrUpdateFence(jsonObject, customerId, operation));
        }
    }

    /**
     * 查询设备围栏
     *
     * @param imei
     * @param request
     * @return
     */
    @GetMapping("/queryFence")
    public RespEntity queryFence(@RequestParam("imei") String imei, HttpServletRequest request) {
        logger.info("queryFence : imei = {}", imei);
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        return new RespEntity(RespCode.SUCCESS, customerService.getDeviceFenceList(imei));
    }

//    /**
//     * 绑定学生
//     *
//     * @param jsonObject
//     * @return
//     */
//    @PostMapping("/bindingStudent")
//    public RespEntity bindingStudent(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
//        String studentName = jsonObject.getString("stuName");
//        String imei = jsonObject.getString("imei");
//        if (Tools.stringIsBlank(imei, studentName)) {
//            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
//        }
//        logger.info("bindingStudent : imei = {},stuName = {}", imei, studentName);
//          Object object = verifyDevice(request,imei);
//        if(object instanceof RespCode){
//            return new RespEntity((RespCode)object);
//        }
//        DeviceInfo deviceInfo = (DeviceInfo)object;
//        if (deviceInfo == null) {
//            return new RespEntity(RespCode.NO_PERMISSION_VIEW_THIS_DATA);
//        }
//        return customerService.bindingStudent(imei, studentName);
//    }

    /**
     * 设置亲情号
     *
     * @param request
     * @param jsonObject
     * @return
     */
    @PostMapping("/setAffection")
    public RespEntity setAffection(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setAffection : param = {}", jsonObject);
        String imei = jsonObject.getString("imei");
        String affection = jsonObject.getString("affection");
        if (Tools.stringIsBlank(imei, affection)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        JSONArray jsonArray = JSONArray.parseArray(affection);
        // 校验sequence是否大于3
        List<Integer> seqList = jsonArray.stream().map(json -> ((JSONObject) json).getInteger("sequence")).collect(Collectors.toList());
        int max = seqList.stream().reduce(Integer::max).get();
        if (max > 3) {
            return new RespEntity(RespCode.AFFECTION_CAN_NOT_GREAT_3);
        }
        Iterator<Object> iterator = jsonArray.iterator();
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        DeviceInfo deviceInfo = (DeviceInfo)object;
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if(!isOnline){
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        // 亲情号最多三个，只循环三次。不做对比一次性下发。
        while (iterator.hasNext()) {
            JSONObject json = (JSONObject) iterator.next();
            // 2021年7月22日16:17:46
            int sequence = json.getInteger("sequence") + 3;
            String name = json.getString("name");
            String phone = json.getString("phone");
            String commandNumber = CommandNumberUtil.getCurTime();
            // 为空，表示删除
            if (StringUtils.isBlank(phone)) {
                boolean send = commandSendUtils.delWhiteCall(imei, commandNumber, sequence, isOnline, 0, false);
                if (send) {
                    whiteListService.updateWhiteCallStatus(deviceInfo.getDeviceId(), sequence, Constants.CLASSES_PATTERN_STAY_DELETE, commandNumber);
                }
            }else{
                DeviceWhiteCall deviceWhiteCall = customerService.getDeviceWhiteCallByDeviceIdAndSequence(deviceInfo.getDeviceId(), sequence);
                // 新增
                if (deviceWhiteCall == null) {
                    deviceWhiteCall = new DeviceWhiteCall();
                    deviceWhiteCall.setDeviceId(deviceInfo.getDeviceId());
                    deviceWhiteCall.setImei(imei);
                    deviceWhiteCall.setName(name);
                    deviceWhiteCall.setPhone(phone);
                    deviceWhiteCall.setSequence(sequence);
                    deviceWhiteCall.setCommandNumber(commandNumber);
                    boolean send = commandSendUtils.addWhiteCall(deviceWhiteCall, isOnline, 0, false);
                    if (send) {
                        deviceWhiteCall.setStatus(Constants.CLASSES_PATTERN_STAY_ADD);
                        whiteListService.addDeviceWhiteCall(deviceWhiteCall);
                    }
                } else {
                    // 修改
                    deviceWhiteCall.setImei(imei);
                    deviceWhiteCall.setName(name);
                    deviceWhiteCall.setPhone(phone);
                    boolean send = commandSendUtils.updateDeviceWhiteCall(deviceWhiteCall, isOnline, 0, false);
                    if (send) {
                        whiteListService.updateWhiteCallStatus(deviceInfo.getDeviceId(), sequence, Constants.CLASSES_PATTERN_STAY_UPDATE, commandNumber);
                    }
                }
            }
        }
        return new RespEntity(RespCode.SUCCESS);
    }

    /**
     * 设置SOS号码
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/setSOSPhone")
    public RespEntity setSOSPhone(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("setSOSPhone : param = {}", jsonObject);
        String imei = jsonObject.getString("imei");
        String sos = jsonObject.getString("sos");
        if (Tools.stringIsBlank(imei, sos)) {
            return new RespEntity(RespCode.PARAMETERIS_MiSSING);
        }
        JSONArray jsonArray = JSONArray.parseArray(sos);
        // 校验sequence是否大于3
        List<Integer> seqList = jsonArray.stream().map(json -> ((JSONObject) json).getInteger("sequence")).collect(Collectors.toList());
        int max = seqList.stream().reduce(Integer::max).get();
        if (max > 3) {
            return new RespEntity(RespCode.SOS_CAN_NOT_GREAT_3);
        }
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        DeviceInfo deviceInfo = (DeviceInfo)object;
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if(!isOnline){
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        boolean sendResult = compareAndSetSosPhone(jsonArray, isOnline, deviceInfo);
        if (!sendResult) {
            return new RespEntity(RespCode.FAILED);
        }
        return new RespEntity(RespCode.SUCCESS);
    }

    /**
     * 批量设置白名单
     *
     * @param jsonObject
     * @param request
     * @return
     */
    @PostMapping("/batchSetWhiteCall")
    public RespEntity batchSetWhiteCall(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
        logger.info("batchSetWhiteCall : param = {}", jsonObject);
        String imei = jsonObject.getString("imei");
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        String whiteCall = jsonObject.getString("whiteCall");
        boolean isOnline = commandSendUtils.deviceOnline(imei);
        if(!isOnline){
            return new RespEntity(RespCode.DEVICE_NOT_ONLINE);
        }
        List<Map<String, Object>> whiteCallList = (List<Map<String, Object>>) JSONArray.parse(whiteCall);
        List<Integer> seqList = whiteCallList.stream().map(map -> (Integer) map.get("sequence")).collect(Collectors.toList());
        int max = seqList.stream().reduce(Integer::min).get();
        if (max < 6) {
            return new RespEntity(RespCode.WHITE_CALL_SEQ_NEED_LARGE_7);
        }
        String commandNumber = CommandNumberUtil.getCurTime();
        boolean send = commandSendUtils.setAllWhiteCall(whiteCallList, imei, commandNumber, isOnline, 0, false);
        if (!send) {
            return new RespEntity(RespCode.FAILED);
        }
        return new RespEntity(RespCode.SUCCESS);
    }

    /**
     * 获取SOS号码列表
     *
     * @param imei
     * @param request
     * @return
     */
    @GetMapping("/getSOSPhoneList")
    public RespEntity getSOSPhoneList(@RequestParam("imei") String imei, HttpServletRequest request) {
        logger.info("getSOSPhoneList : imei = {}", imei);
          Object object = verifyDevice(request,imei);
        if(object instanceof RespCode){
            return new RespEntity((RespCode)object);
        }
        DeviceInfo deviceInfo = (DeviceInfo)object;
        List<DeviceSOSList> sosLists = customerService.getDeviceSosPhoneList(deviceInfo.getDeviceId());
        return new RespEntity(RespCode.SUCCESS, sosLists);
    }

    /**
     * 校验客户是否能操作该设备
     *
     * @param request
     * @param imei
     * @return
     */
    private Object verifyDevice(HttpServletRequest request, String imei) {
        String accessToken = request.getHeader("Access-Token");
        Integer customerId = 0;
        DeviceInfo deviceInfo = null;
        try{
            customerId = redisService.customerToken2CustomerId(accessToken);
        }catch (Exception e){
            return RespCode.SUCCESS;
        }
        try{
            deviceInfo = deviceInfoService.verifyDeviceCustomer(imei, customerId);
        }catch(Exception e){
            return RespCode.NO_PERMISSION_VIEW_THIS_DATA;
        }
        if(deviceInfo == null){
            return RespCode.NO_PERMISSION_VIEW_THIS_DATA;
        }
        return deviceInfo;
    }

    /**
     * 对比并且设置号码
     *
     * @param jsonArray
     * @param isOnline
     * @param deviceInfo
     */
    public boolean compareAndSetSosPhone(JSONArray jsonArray, boolean isOnline, DeviceInfo deviceInfo) {
        List<DeviceSOSList> sosList = customerService.getDeviceSosPhoneList(deviceInfo.getDeviceId());
        List<DeviceSOSList> sendList = new ArrayList<>();
        Map<Integer, Object> dataBaseOperation = new HashMap<>();
        String commandNumber = CommandNumberUtil.getCurTime();

        // 固定三层循环，表示序列号123；
        for (int i = 1; i <= 3; i++) {
            DeviceSOSList send = null;
            boolean sendFlag = false;
            // 1- 先遍历传过来的设备，遍历完能够知道传过来的操作。只有这个有操作。
            Iterator<Object> iterator = jsonArray.iterator();
            while (iterator.hasNext()) {
                JSONObject json = (JSONObject) iterator.next();
                Integer sequence = json.getInteger("sequence");
                String phone = json.getString("phone");
                String name = json.getString("name");
                // 如果有，发送这个
                if (i == sequence.intValue()) {
                    send = new DeviceSOSList();
                    send.setSequence(sequence);
                    send.setSosPhone(phone);
                    send.setSosName(name);
                    sendFlag = true;
                    // 1.1 判断此次操作（增删改）
                    if (StringUtils.isBlank(phone)) {
                        dataBaseOperation.put(i, "del");
                    } else {
                        // 区分增加和修改；默认为增加
                        boolean flag = true;
                        for (DeviceSOSList sosPhone : sosList) {
                            if (sosPhone.getSequence().intValue() == i) {
                                dataBaseOperation.put(i, jsonArray);
                                flag = false;
                                break;
                            }
                        }
                        // true为增加 false为修改
                        if (flag) {
                            dataBaseOperation.put(i, json);
                        } else {
                            dataBaseOperation.put(i, sequence);
                        }
                    }
                }
            }
            if (sendFlag) {
                sendList.add(send);
            } else {
                //2-如果传过来的数据没有这个序列号，从数据库中查找。
                boolean dataBaseHas = false;
                for (DeviceSOSList sosPhone : sosList) {
                    if (sosPhone.getSequence().intValue() == i) {
                        send = sosPhone;
                        dataBaseHas = true;
                        break;
                    }
                }
                // 3-如果数据库也没有，构建一个空的发过去，但是无数据库操作
                if (!dataBaseHas) {
                    send = new DeviceSOSList();
                    send.setSequence(i);
                    send.setSosName("");
                    send.setSosPhone("");
                }
                sendList.add(send);
            }
        }
        // 发送指令
        boolean send = commandSendUtils.setAllSosCall(sendList, deviceInfo.getImei(), commandNumber, isOnline, 0, false);
        if (send) {
            // 遍历map,进行状态修改
            for (Map.Entry<Integer, Object> entry : dataBaseOperation.entrySet()) {
                int seq = entry.getKey();
                Object value = entry.getValue();
                // 删除
                if (value instanceof String) {
                    customerService.updateSosPhoneStatus(deviceInfo.getDeviceId(), seq, Constants.CLASSES_PATTERN_STAY_DELETE, commandNumber);
                } else if (value instanceof Integer) {
                    customerService.updateSosPhoneStatus(deviceInfo.getDeviceId(), seq, Constants.CLASSES_PATTERN_STAY_UPDATE, commandNumber);
                } else {  // 新增
                    String name = ((JSONObject) value).getString("name");
                    String phone = ((JSONObject) value).getString("phone");
                    customerService.addSosPhone(deviceInfo.getDeviceId(), seq, name, phone, Constants.CLASSES_PATTERN_STAY_ADD, commandNumber);
                }
            }
        }
        return send;
    }

}
